use std::sync::Arc;
use tokio::sync::RwLock;
use tonic::transport::Channel;
use tracing::info;

use crate::proto::{
    nacos_service_client::NacosServiceClient,
    ClusterRequest, ClusterResponse,
    DataSyncRequest, DataSyncResponse,
    MemberChangeRequest, MemberChangeResponse,
    HealthCheckRequest, HealthCheckResponse,
};

/// gRPC客户端
#[derive(Debug)]
pub struct GrpcClient {
    address: String,
    client: Arc<RwLock<NacosServiceClient<Channel>>>,
}

impl Clone for GrpcClient {
    fn clone(&self) -> Self {
        Self {
            address: self.address.clone(),
            client: self.client.clone(),
        }
    }
}

impl GrpcClient {
    /// 创建新的gRPC客户端
    pub async fn new(address: String) -> Result<Self, tonic::transport::Error> {
        let endpoint = format!("http://{}", address);
        let client = NacosServiceClient::connect(endpoint).await?;
        
        info!("连接到gRPC服务: {}", address);
        
        Ok(Self {
            address,
            client: Arc::new(RwLock::new(client)),
        })
    }

    /// 发送心跳
    pub async fn send_heartbeat(
        &self,
        from_node: String,
    ) -> Result<ClusterResponse, tonic::Status> {
        let request = ClusterRequest {
            request_type: "heartbeat".to_string(),
            from_node,
            data: String::new(),
        };

        let mut client = self.client.write().await;
        let response = client.handle_cluster_request(request).await?;
        Ok(response.into_inner())
    }

    /// 获取节点信息
    pub async fn get_node_info(
        &self,
        from_node: String,
    ) -> Result<ClusterResponse, tonic::Status> {
        let request = ClusterRequest {
            request_type: "node_info".to_string(),
            from_node,
            data: String::new(),
        };

        let mut client = self.client.write().await;
        let response = client.handle_cluster_request(request).await?;
        Ok(response.into_inner())
    }

    /// 同步数据
    pub async fn sync_data(
        &self,
        sync_type: String,
        from_node: String,
        data: String,
        version: u64,
    ) -> Result<DataSyncResponse, tonic::Status> {
        let request = DataSyncRequest {
            sync_type,
            from_node,
            data,
            version,
            timestamp: std::time::SystemTime::now()
                .duration_since(std::time::UNIX_EPOCH)
                .unwrap()
                .as_secs(),
        };

        let mut client = self.client.write().await;
        let response = client.handle_data_sync(request).await?;
        Ok(response.into_inner())
    }

    /// 处理成员变更
    pub async fn member_change(
        &self,
        action: String,
        node_id: String,
        node_info: String,
    ) -> Result<MemberChangeResponse, tonic::Status> {
        let request = MemberChangeRequest {
            action,
            node_id,
            node_info,
        };

        let mut client = self.client.write().await;
        let response = client.handle_member_change(request).await?;
        Ok(response.into_inner())
    }

    /// 健康检查
    pub async fn health_check(
        &self,
        target_node: String,
    ) -> Result<HealthCheckResponse, tonic::Status> {
        let request = HealthCheckRequest {
            target_node,
        };

        let mut client = self.client.write().await;
        let response = client.health_check(request).await?;
        Ok(response.into_inner())
    }

    /// 重新连接
    pub async fn reconnect(&mut self) -> Result<(), tonic::transport::Error> {
        let endpoint = format!("http://{}", self.address);
        let client = NacosServiceClient::connect(endpoint).await?;
        
        *self.client.write().await = client;
        info!("重新连接到gRPC服务: {}", self.address);
        
        Ok(())
    }

    /// 获取连接地址
    pub fn address(&self) -> &str {
        &self.address
    }
}